package com.tianjin.design.memento;

/**
 *
 * @author tianjin
 *
 * 2023年6月12日
 * TODO 备忘录模式# 行为型模式
 *
 * 1、基本解释：在不破坏封装性的前提下，获取到一个对象当前时刻的内部状态，并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
 * 2、使用场景：Memento 备忘录模式比较适合用于功能比较复杂的，但需要保存属性历史的类
 * 3、个人理解：将对象某一个时刻的状态信息存储下来，后续可以恢复对象至某一个时刻的状态，所以在实现上是这样考虑的
 * 			需要有一个要保存的对象，GameRole ，有血量、经验值等
 * 				最初考虑到的一个问题： 记录历史状态既然不存放到磁盘上，为什么不直接通过new一个GameRole或new之后赋值的方式实现，而是新增几个类，通过备忘录模式实现呢？
 * 					后续自己的想法是这样：根据单一职责原则，GameRole就是用来表示游戏角色的，如果在用来记录历史状态，违背此原则，
 * 					如果通过给属性赋值的方式实现，直接就暴露了细节，破坏了封装性，只要破坏了封装性，后续扩展就困难了，例如加一个“能量值”字段，则需要全部修改一遍
 * 			所以需要使用外部对象来存储当前对象历史某个时刻的状态信息，此外部对象需要存在备忘的部分或全部属性信息 ,此就是备忘录对象  GameRoleMemento
 * 				为了防止其他对象访问 GameRoleMemento 的属性，所以不提供外部方法，只允许 GameRole 创建
 *
 * 			通过以上思路开发代码为版本一，此时感觉没有问题，其实自己研究会发现， 在外部可以操作 GameRoleMemento 对象的属性，也就是可以简介获取到 GameRole 的属性
 * 				这种情况下，因为可以直接获取，所以客户端还是增加了可维护性，所以，通常需要一个备忘录管理器
 *
 * 			根据上方实战，可以还需要一个备忘录管理器 GameRoleMementoCaretaker， 用GameRoleMementoCaretaker来获取备忘录，这样对外就暴露最少了，依赖倒置原则
 *
 * 			见版本二
 * 				此时，对于客户端来说，是无视GameRoleMemento存在的，屏蔽了细节，只需要使用GameRoleMementoCaretaker使用备忘录即可
 */
public class Test {

	public static void main(String[] args) {

		/* 版本一

		GameRole gameRole = new GameRole(100, 100);
		System.out.println("初始游戏角色状态："+ gameRole.toString());

		System.out.println("对战之前先存档...  存档成功");
		GameRoleMemento gameRoleMemento = gameRole.createMemento();

		System.out.println("与boss对战中，被boss杀死");
		gameRole.kill();

		System.out.println("杀死后游戏角色状态："+ gameRole.toString());

		System.out.println("提取存档信息... 恢复进度");
		gameRole.resetGameRole(gameRoleMemento);

		System.out.println("恢复后游戏角色状态："+ gameRole.toString());

		*/

		// 版本二
		GameRole gameRole = new GameRole(100, 100);
		System.out.println("初始游戏角色状态："+ gameRole.toString());

		System.out.println("对战之前先存档...  存档成功");
		GameRoleMementoCaretaker caretaker = new GameRoleMementoCaretaker();
		caretaker.setMeoMemento(gameRole.createMemento());

		System.out.println("与boss对战中，被boss杀死");
		gameRole.kill();

		System.out.println("杀死后游戏角色状态："+ gameRole.toString());

		System.out.println("提取存档信息... 恢复进度");
		gameRole.resetGameRole(caretaker.getMeoMemento());

		System.out.println("恢复后游戏角色状态："+ gameRole.toString());
		System.out.println("可以继续在boss阶段闯关了");

	}
}
